const constants = require('../helpers/constants');
const utils = require('../helpers/utils');
const lodash = require('lodash');
const dayjs = require('dayjs');

/**
 * 获取openapi
 * @param {Array} tableList Table对象集合
 */
function parse({
    tableList = [],
    title,
    description,
    contactName,
    contactEmail,
    license = {
        name: 'Apache 2.0',
        url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
    },
    servers = [],
    security = 'BearerAuth'
}) {
    const defaultSchemas = lodash.cloneDeep(getDefaultSchemas());
    const schemas = { ...defaultSchemas };
    const tags = [];
    let paths = {
        ...getDefaultPaths()
    };
    tableList.forEach((table) => {
        const tag = table.name;
        const model = utils.capitalize(table.name);
        const modelDesc = table.description && table.description.replace(/表$/, '');
        // 添加新标签
        tags.push({ name: tag, description: modelDesc });
        // 设置schema
        schemas[model] = getSchema(table, modelDesc);
        schemas[`${model}PageBean`] = getPageBeanSchema(model, modelDesc);
        // 设置请求路径
        paths = {
            ...paths,
            ...getListPath(tag, model, modelDesc),
            ...getBaseOperatePath(tag, model, modelDesc)
        };
    });
    return {
        openapi: '3.0.0',
        info: {
            title,
            description,
            contact: {
                name: contactName,
                email: contactEmail
            },
            license,
            version: '1.0.0'
        },
        security: [
            {
                [security]: []
            }
        ],
        servers,
        tags,
        paths,
        components: {
            schemas,
            securitySchemes: getSecurityScheme(security)
        }
    };
}

/**
 * 获取默认的schemas
 * @returns
 */
function getDefaultSchemas() {
    return Object.freeze({
        PageBean: {
            type: 'object',
            properties: {
                current: {
                    type: 'integer',
                    description: '当前页',
                    format: 'int32'
                },
                size: {
                    type: 'integer',
                    description: '当前页分页大小',
                    format: 'int32'
                },
                total: {
                    type: 'integer',
                    description: '总数',
                    format: 'int64'
                }
            },
            description: '分页对象'
        },
        Result: {
            type: 'object',
            properties: {
                code: {
                    type: 'integer',
                    description: '响应代码',
                    format: 'int64'
                },
                msg: {
                    type: 'string',
                    description: '响应消息'
                }
            },
            description: '响应结果'
        }
    });
}

/**
 * 获取默认的schemas
 * @returns
 */
function getDefaultPaths() {
    return Object.freeze({
        '/user/login': {
            post: {
                tags: ['user'],
                summary: '用户登录到系统',
                operationId: 'loginUser',
                security: [],
                parameters: [
                    {
                        name: 'username',
                        in: 'query',
                        description: '登录用户名',
                        required: true,
                        schema: {
                            type: 'string'
                        }
                    },
                    {
                        name: 'password',
                        in: 'query',
                        description: '明文登录密码',
                        required: true,
                        schema: {
                            type: 'string',
                            format: 'password'
                        }
                    }
                ],
                responses: {
                    200: {
                        description: '成功响应',
                        headers: {
                            'Authorization': {
                                description: 'JWT授权token',
                                schema: {
                                    type: 'string'
                                }
                            }
                        }
                    },
                    400: {
                        description: '提供的用户名密码无效',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            }
        },
        '/user/logout': {
            get: {
                tags: ['user'],
                summary: '注销当前已登录的用户会话',
                operationId: 'logoutUser',
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            }
        }
    });
}

/**
 * 获取openapi schema
 * @param {Object} table Table对象
 * @returns
 */
function getSchema(table, desc) {
    const properties = {};
    const requiredFields = [];
    table.fields.forEach((field) => {
        const apiType = constants.SQL_TYPES[field.type];
        if (field.required) {
            requiredFields.push(field.name);
        }
        properties[field.name] = {
            ...apiType,
            default: getValidValue(field.default),
            description: field.description
        };
    });
    return {
        type: 'object',
        description: desc,
        required: requiredFields,
        properties: properties
    };
}

/**
 *  获取一个有效值
 * @param {String} value 默认值
 */
function getValidValue(value) {
    if (/\(/.test(value)) {
        return null;
    } else if (/^current_timestamp$/.test(value)) {
        return dayjs().format('YYYY-MM-DD HH:mm:ss');
    }
    return value;
}

/**
 * 获取分页schema
 * @param {String} name 实体名
 * @param {String} desc 实体描述
 * @returns
 */
function getPageBeanSchema(name, desc) {
    return {
        allOf: [
            {
                $ref: '#/components/schemas/PageBean'
            },
            {
                type: 'object',
                properties: {
                    records: {
                        type: 'array',
                        description: `${desc}列表`,
                        items: {
                            $ref: `#/components/schemas/${name}`
                        }
                    }
                }
            }
        ]
    };
}

/**
 * 获取列表查询对象
 * @param {String} tag 标签
 * @param {String} name 实体
 * @param {String} desc 实体描述
 * @returns 列表查询对象
 */
function getListPath(tag, name, desc) {
    return {
        [`/${tag}/list`]: {
            get: {
                tags: [tag],
                summary: `查询${desc}列表（分页）`,
                description: `分页查询${desc}，提供关键字筛选`,
                operationId: `query${name}List`,
                parameters: [
                    {
                        name: 'current',
                        in: 'query',
                        description: '当前页（默认为1）, -1查询所有',
                        required: false,
                        style: 'form',
                        explode: true,
                        schema: {
                            type: 'integer',
                            format: 'int32',
                            default: 1
                        }
                    },
                    {
                        name: 'size',
                        in: 'query',
                        description: '分页大小（默认为20）',
                        required: false,
                        style: 'form',
                        explode: true,
                        schema: {
                            type: 'integer',
                            format: 'int32',
                            default: 20
                        }
                    },
                    {
                        name: 'keyword',
                        in: 'query',
                        description: '关键字',
                        required: false,
                        style: 'form',
                        explode: true,
                        schema: {
                            type: 'string'
                        }
                    }
                ],
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: `#/components/schemas/${name}PageBean`
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            }
        }
    };
}

/**
 * 获取增删改查对象
 * @param {String} tag 标签
 * @param {String} name 实体
 * @param {String} desc 实体描述
 * @returns 增删改查对象
 */
function getBaseOperatePath(
    tag,
    name,
    desc,
    idType = {
        type: 'string'
    }
) {
    return {
        [`/${tag}`]: {
            get: {
                tags: [tag],
                summary: `查询${desc}详情`,
                description: `通过ID查询${desc}详情`,
                operationId: `get${name}`,
                parameters: [
                    {
                        name: 'id',
                        in: 'query',
                        description: `${desc}ID`,
                        required: true,
                        style: 'form',
                        explode: true,
                        schema: idType
                    }
                ],
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: `#/components/schemas/${name}`
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            },
            post: {
                tags: [tag],
                summary: `新增${desc}`,
                description: `新增${desc}`,
                operationId: `add${name}`,
                requestBody: {
                    description: `添加${desc}`,
                    content: {
                        'application/json': {
                            schema: {
                                $ref: `#/components/schemas/${name}`
                            }
                        }
                    },
                    required: true
                },
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            },
            delete: {
                tags: [tag],
                summary: `删除${desc}`,
                description: `删除${desc}`,
                operationId: `delete${name}`,
                parameters: [
                    {
                        name: 'id',
                        in: 'query',
                        description: `${desc}id`,
                        required: true,
                        style: 'form',
                        explode: true,
                        schema: idType
                    }
                ],
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            },
            patch: {
                tags: [tag],
                summary: `修改${desc}`,
                description: `修改${desc}`,
                operationId: `patch${name}`,
                requestBody: {
                    description: `修改${desc}`,
                    content: {
                        'application/json': {
                            schema: {
                                $ref: `#/components/schemas/${name}`
                            }
                        }
                    },
                    required: true
                },
                responses: {
                    200: {
                        description: '成功响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    401: {
                        description: '用户权限不足',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    },
                    default: {
                        description: '响应',
                        content: {
                            'application/json': {
                                schema: {
                                    $ref: '#/components/schemas/Result'
                                }
                            }
                        }
                    }
                }
            }
        }
    };
}

/**
 *
 * @param {String} category 认证类型（BasicAuth、BearerAuth、ApiKeyAuth、OpenID、OAuth2）
 */
function getSecurityScheme(category) {
    if (!category) {
        return {};
    }
    const securitySchemes = {
        BasicAuth: {
            type: 'http',
            scheme: 'basic'
        },
        BearerAuth: {
            type: 'http',
            scheme: 'bearer'
        },
        ApiKeyAuth: {
            type: 'apiKey',
            in: 'header',
            name: 'X-API-Key'
        },
        OpenID: {
            type: 'openIdConnect',
            openIdConnectUrl: 'https://example.com/.well-known/openid-configuration'
        },
        OAuth2: {
            type: 'oauth2',
            flows: {
                authorizationCode: {
                    authorizationUrl: 'https://example.com/oauth/authorize',
                    tokenUrl: 'https://example.com/oauth/token',
                    scopes: {
                        read: 'Grants read access',
                        write: 'Grants write access',
                        admin: ' Grants access to admin operations'
                    }
                }
            }
        }
    };
    return {
        [category]: securitySchemes[category]
    };
}

module.exports = {
    parse
};
